#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import os
import sys
import re
import time
import errno
import commands

admin_path = os.path.abspath(os.path.split(os.path.realpath(__file__))[0])
sys.path.insert(0, "%s/../" % (admin_path))

from buddha.lichbd import Lichbd

from gbase_utils import parser, _derror, _exec_cmd, _time_str


class GbaseCluster(object):

    def __init__(self):
        self.lich = '/opt/fusionstack/lich/bin/lich'
        self.lichinspect = '/opt/fusionstack/lich/bin/lich.inspect'
        self.parser_conf()

        self.lichbd = Lichbd()

    def parser_conf(self):
        conf = parser()
        self.cluster_conf = conf['cluster']
        self.node_conf = conf['nodes']
        self.pools_conf = conf['pools']

        self.num = self.cluster_conf['num']
        if len(self.node_conf) != self.num:
            _derror('Cluster MAX num not equal to nodes count')
            exit(errno.EINVAL)

        self.passwd = self.cluster_conf['password']
        self.net = self.cluster_conf['net']
        self.hosts = self.parser_hosts()
        self.pools = self.parser_pools()

    def parser_hosts(self):
        hosts = {}
        net = '.'.join(self.net.split('.')[:-1])

        for node in self.node_conf:
            for name, nets in node.iteritems():
                for eth, ip in nets.iteritems():
                    if net in ip:
                        hosts[name] = ip.split('/')[0]

        return hosts

    def parser_pools(self):
        pools = self.pools_conf
        for pool, pinfo in pools.iteritems():
            prio = 0 if pinfo['type'] == 'ssd' else 1
            pinfo['prio'] = prio
        return pools

    '''
        1.设置/etc/host
    '''
    def set_etchosts(self):
        hosts = self.hosts
        path = '/etc/hosts'
        lines = []
        etc = []
        if os.path.exists(path):
            with file(path, 'r') as p_file:
                etc = p_file.readlines()

        fd = open(path, 'a+')
        for name, ip in hosts.iteritems():
            line = '%s %s\n' % (ip, name)
            if line not in etc:
                lines.append(line)
                fd.write(line)
        fd.flush()
        fd.close()

    '''
        2.配置lich.conf
    '''
    def setup_lichconf(self):
        path = '/opt/fusionstack/etc/lich.conf'
        cluster_name = 'gbase'
        network = self.net

        cmd0 = 'sed -ri s"%%^\s*#clustername XXX;%%\tclustername %s;%%g" %s' % (cluster_name, path)
        cmd = 'sed -ri s"%%^\s*([0-9]{1,3}.){3}[0-9]{1,3}/[0-9]{1,3}%%\t\t%s%%g" %s' % (network, path)
        date = _time_str(time.time())
        cmd1 = 'sed -ri s"%%^\s*#iqn iqn.2001-04-XXX.com.fusionstack;%%\tiqn iqn.%s.com.fusionstack;%%g" %s' % (date, path)
        try:
            _exec_cmd(cmd0, "set clustername failed")
            _exec_cmd(cmd, "set network failed")
            _exec_cmd(cmd1, "set iqn failed")
        except Exception, e:
            _derror("update etc failed : " + e.err)
            raise

    '''
        3.集群prep
    '''
    def prep(self):
        passwd = self.passwd
        hosts = self.hosts.keys()
        cmd = '%s prep %s' % (self.lich, ' '.join(hosts))
        cmd += ' -p %s' % (passwd)
        _exec_cmd(cmd, 'lich prep failed')

    '''
        4.分发host
    '''
    def dispatch_etchosts(self):
        path = '/etc/hosts'
        hosts = self.hosts
        try:
            for name, ip in hosts.iteritems():
                cmd = 'scp -o StrictHostKeyChecking=no %s root@%s:%s' % (
                        path, name, path)
                _exec_cmd(cmd, "dispathc etc hosts to %s failed" % ip)
        except Exception as e:
            _derror('update etc hosts failed : ' + e.err)
            raise

    '''
        5.集群创建
    '''
    def cluster_create(self):
        created = False

        conf = '/opt/fusionstack/etc/cluster.conf'
        cmd = 'ls ' + conf
        status, out = commands.getstatusoutput(cmd)
        if out == conf:
            created = True

        hosts = self.hosts.keys()
        cmd = '%s create %s' % (self.lich, ' '.join(hosts))
        if not created:
            _exec_cmd(cmd, "lich create failed")

        cmd = "%s list |grep admin" % (self.lich)
        try:
            status, out = commands.getstatusoutput(cmd)
            if status != 0 or not out.strip():
                raise
        except Exception as e:
            _derror('no admin :' + e.err)
            exit(1)

    '''
        6.添加磁盘
    '''
    def disk_add(self):
        err = "add disks failed"
        cmd = '%s add disk --force' % (self.lich)
        _exec_cmd(cmd, err)

        cmd = '%s stat' % (self.lich)
        status, out = commands.getstatusoutput(cmd)
        m = re.search("capacity:(\d+\.*\d*)\S*", out)
        if status != 0 or m is None or float(m.group(1)) <= 0:
            _derror(err)
            exit(1)

    def pool_create(self):
        ''' 7.pool创建
        '''
        for pool in self.pools:
            self.lichbd.pool_create(pool)

    def volume_create(self):
        ''' 8.volume创建
        '''
        protocol = 'iscsi'
        pools = self.pools
        for pool, pinfo in pools.iteritems():
            prio = pinfo['prio']
            luns = pinfo['luns']
            for lun, size in luns.iteritems():
                self.lichbd.vol_create('%s/%s' % (pool, lun), size, protocol=protocol)

                cmd = '%s --priority /%s/%s %d' % (self.lichinspect, protocol, lun, prio)
                _exec_cmd(cmd)

    def run(self):
        print '''
        1.设置/etc/host
        2.配置lich.conf
        3.集群prep
        4.分发host
        5.集群创建
        6.添加磁盘
        7.pool创建
        8.volume创建
        '''

        print 'step 1 : 设置 hosts ...'
        self.set_etchosts()
        print 'step 1 successed'

        print 'step 2 : 配置 conf ...'
        self.setup_lichconf()
        print 'step 2 successed'

        print 'step 3 : 集群 prep ...'
        self.prep()
        print 'step 3 successed'

        print 'step 4 : 分发 etchosts ...'
        self.dispatch_etchosts()
        print 'step 4 successed'

        print 'step 5 : 集群 cluster ...'
        self.cluster_create()
        print 'step 5 successed'

        print 'step 6 : 磁盘 add ...'
        self.disk_add()
        print 'step 6 successed'

        print 'step 7 : 创建 pool ...'
        self.pool_create()
        print 'step 7 successed'

        print 'step 8 : 创建 volume ...'
        self.volume_create()
        print 'step 8 successed'

if __name__ == "__main__":
    gbc = GbaseCluster()
    gbc.run()

    print("\nSuccessed!")
